package com.applcn.core.log;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder;

import javax.servlet.http.HttpServletResponseWrapper;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * FIXME 需要解决读流
 */
@Aspect
@Slf4j
@Order(1)
public class GlobalLogsInterceptor {

    @Pointcut(value = "@within(org.springframework.web.bind.annotation.RestController) || @within(org.springframework.stereotype.Controller)")
    public void pointAspect() {}

    @Around("pointAspect()")
    public void afterPointAspect(ProceedingJoinPoint joinPoint) throws Throwable {
        //方法执行前获取当前时间
        long start = System.currentTimeMillis();
        String className = joinPoint.getSignature().getName();
        log.info("方法名： {}", className.substring(className.lastIndexOf(".") + 1));
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        methodBefore(joinPoint, uuid);
        Object proceed = joinPoint.proceed();
        methodAfterReturing(proceed, uuid);

        //响应结果
        Object result = joinPoint.proceed(joinPoint.getArgs());
        //方法执行后获取当前时间
        long end = System.currentTimeMillis();
        log.info("响应结果：{}", result);
        log.info("方法执行时间：{} 毫秒", end - start);
    }

    public void methodBefore(JoinPoint joinPoint, String uuid) {
        Object[] objs = joinPoint.getArgs();
        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        Map<String, Object> paramMap = new HashMap<>();
        for (int i = 0; i < objs.length; i++) {
            if (!(objs[i] instanceof ExtendedServletRequestDataBinder) && !(objs[i] instanceof HttpServletResponseWrapper)) {
                paramMap.put(argNames[i], objs[i]);
            }
        }
        if (paramMap.size() > 0) {
            log.info("方法:{},参数:{}", joinPoint.getSignature(), JSONObject.toJSONString(paramMap));
        }
    }

    public void methodAfterReturing(Object o, String uuid) {
        if (o != null) {
            log.info("响应内容:{}", JSONObject.toJSON(o));
        }
    }
}
